package org.example.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 演示 @Value , Environment 注解取值
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2021/8/8 9:53
 */
@RestController
@SuppressWarnings("all")
public class ValueController {

    //直接从容器中获取即可, Spring 框架已经默认提供了.
    @Autowired
    private Environment environment;

    //赋值普通的Java数据类型值
    @Value("v2.3.1")
    private String version;

    //${key}：从环境变量以及配置文件中取值，如果值不存在，则设置分号后面的默认值
    @Value(value = "${app.info.str:xxx}")
    private String str;

    @Value("${app.info.int:0}")
    private int integer;

    @Value("${app.info.date:1993/08/20}")
    private Date date;

    //数组可以直接取值，不存在时使用分号后面的默认值，分号后面什么都没有时，表示数组为空数组，长度为0
    @Value("${app.info.array1:}")
    private String[] array1;

    @Value("${app.info.array2:A,B,C}")
    private String[] array2;

    //#{SpEL}：Spring 表达式语言
    @Value("#{20.5* 1000}")
    private float salary;

    /**
     * @Value 注解无法直接注入 List 类型，必须通过数组 + SpEl 表达式语言进行转换
     * 第一个 $ 取值表示如果不存在，则数组默认为空，当数组为空(.empty)，则让 list 默认为空，
     * 否则不为空时，使用 split 函数用逗号将数组分割转为 list.
     */
    @Value("#{'${app.info.arrayToList:}'.empty ? '': '${app.info.arrayToList:}'.split(',')}")
    private List<String> list;

    /**
     * @Value 注解无法直接注入 Set 类型，必须通过数组 + SpEl 表达式语言进行转换
     * 第一个 $ 取值表示如果不存在，则数组默认为空，当数组为空(.empty)，则让 Set 默认为：大汉,大隋，
     * 否则不为空时，使用 split 函数用逗号将数组分割转为 Set.
     * set 操作与 list 完全一样，只是 set 会自动去重.
     */
    @Value("#{'${app.info.arrayToList:}'.empty ? '大汉,大隋': '${app.info.arrayToList:}'.split(',')}")
    private Set<String> set;

    //@Value 获取 Map 属性时，暂时不知道如何设置默认值
    @Value("#{${app.info.cityMap}}")
    private Map<String, Object> map;

    /**
     * 获取服务端口，不配置时，默认为 80
     * [@Value] 注解在服务启动时就会自动注入，所以被标记的方法在服务启动时就会自动执行
     *
     * @param dbDriver
     */
    @Value("${server.port:80}")
    private void getServerPort(String serverPort) {
        System.out.println("服务端口(serverPort)=" + serverPort);
    }

    /**
     * http://localhost:8080/value/get
     *
     * @return
     */
    @GetMapping("value/get")
    public Map<String, Object> getValue() {
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("version", version);
        resultMap.put("str", str);
        resultMap.put("integer", integer);
        resultMap.put("date", date);
        resultMap.put("array1", array1);
        resultMap.put("array2", array2);
        resultMap.put("salary", salary);
        resultMap.put("list", list);
        resultMap.put("set", set);
        resultMap.put("map", map);

        System.out.println(resultMap);
        return resultMap;
    }

    /**
     * {@link Environment} 表示环境, 可用于获取应用程序的属性配置.
     * String getProperty(String key): 返回全局配置文件中与给定 key 关联的属性值, 如果没有,则返回 null.
     * <p>
     * http://localhost:8080/value/environment
     */
    @GetMapping("value/environment")
    public Map<String, Object> environment() {
        Map<String, Object> resultMap = new HashMap<>();

        String str = environment.getProperty("app.info.str");
        String date = environment.getProperty("app.info.date");
        String array2 = environment.getProperty("app.info.array2");
        String arrayToList = environment.getProperty("app.info.arrayToList");
        String cityMap = environment.getProperty("app.info.cityMap");
        String xxx = environment.getProperty("app.info.xxx");

        resultMap.put("str", str);
        resultMap.put("date", date);
        resultMap.put("array2", array2);
        resultMap.put("arrayToList", arrayToList);
        resultMap.put("cityMap", cityMap);
        resultMap.put("xxx", xxx);

        //{"str":"张三","date":"2018/07/11","cityMap":"{\"mapK1\": \"长沙麓谷\",\"mapK2\": \"深圳科技园\"}","arrayToList":"唐,宋,元,明,清","array2":"a,b,c,d,e"}
        return resultMap;
    }


}
